extends EnemyTemplate

enum State {
	IDLE,
	WALK,
	RUN,
	HURT,
	DYING,
}

var pending_damage: Damage

@export var KNOCKBACK_AMOUNT := 512.0

@onready var wall_checker: RayCast2D = $Graphics/WallChecker
@onready var player_checker: RayCast2D = $Graphics/PlayerChecker
@onready var floor_checker: RayCast2D = $Graphics/FloorChecker
@onready var calm_down_timer: Timer = $CalmDownTimer
@onready var stats: Stats = $Stats

func can_see_player() -> bool:
	if not player_checker.is_colliding():
		return false
	return player_checker.get_collider() is Player

# 实现状态机方法
func tick_physics(state: State, delta: float) -> void:
	match state:
		State.IDLE, State.HURT, State.DYING:
			move(0.0, delta)
		State.WALK:
			move(max_speed /3, delta)
		State.RUN:
			if wall_checker.is_colliding() or not floor_checker.is_colliding():
				direction *= -1
			move(max_speed, delta)
			if can_see_player():
				calm_down_timer.start()

func get_next_state(state: State) -> int:
	if stats.health <= 0:
		return StateMachine.KEEP_CURRENT if state == State.DYING else State.DYING
	if pending_damage:
		return State.HURT

	match state:
		State.IDLE:
			if can_see_player():
				return State.RUN
			# 站立一段时间开始走动
			if state_machine.state_time > 2:
				return State.WALK
		State.WALK:
			if can_see_player():
				return State.RUN
			# 走到墙边或悬崖则站立
			if wall_checker.is_colliding() or not floor_checker.is_colliding():
				return State.IDLE
		State.RUN:
			if not can_see_player() and calm_down_timer.is_stopped():
				return State.WALK
		State.HURT:
			if not animation_player.is_playing():
				return State.RUN
				
	return StateMachine.KEEP_CURRENT

func transition_state(from: State, to: State) -> void:
	#print("[%s] %s => %s" % [
		#Engine.get_physics_frames(),
		#State.keys()[from] if from != -1 else "<START>",
		#State.keys()[to]
	#])

	# 在离开需要循环音效的状态时停止音效
	match from:
		State.RUN:
			SoundManager.stop_looping_sfx("BoarRun")
	
	match to:
		State.IDLE:
			animation_player.play("idle")
			# 前方墙壁
			if wall_checker.is_colliding():
				# 转身
				direction *= -1
		State.WALK:
			animation_player.play("walk")
			# 前方悬崖（不是地面）
			if not floor_checker.is_colliding():
				# 转身
				direction *= -1
				# 前置更新碰撞检测状态，防止读取缓存状态
				floor_checker.force_raycast_update()
		State.RUN:
			animation_player.play("run")
			SoundManager.play_looping_sfx("BoarRun")
		State.HURT:
			animation_player.play("hurt")
			stats.health -= pending_damage.amount
			# 受击后退
			var dir := pending_damage.source.global_position.direction_to(global_position)
			velocity = dir * KNOCKBACK_AMOUNT
			# 始终面朝玩家
			direction = Direction.LEFT if dir.x > 0 else Direction.RIGHT
			pending_damage = null
			SoundManager.play_sfx("BoarDamage")
			
		State.DYING:
			animation_player.play("die")


func _on_hurt_box_hurt(hitBox: HitBox) -> void:
	# TODO 根据玩家状态计算扣血
	#if hitBox.owner is Player:
	#stats.health -= 1
	#if stats.health <= 0:
		#queue_free()
	pending_damage = Damage.new()
	pending_damage.amount = 1
	pending_damage.source = hitBox.owner
